/**
   * @description 射线法判断点是否在多边形内部
   * @param {Object} p 待判断的点，格式：{ x: X坐标, y: Y坐标 }
   * @param {Array} poly 多边形顶点，数组成员的格式同 p
   * @return {String} 点 p 和多边形 poly 的几何关系
   */
function rayCasting(p, poly) {
  var px = p.x,
      py = p.y,
      flag = false

  for(var i = 0, l = poly.length, j = l - 1; i < l; j = i, i++) {
    var sx = poly[i].x,
        sy = poly[i].y,
        tx = poly[j].x,
        ty = poly[j].y

    // 点与多边形顶点重合
    if((sx === px && sy === py) || (tx === px && ty === py)) {
      return 'on'
    }

    // 判断线段两端点是否在射线两侧
    if((sy < py && ty >= py) || (sy >= py && ty < py)) {
      // 线段上与射线 Y 坐标相同的点的 X 坐标
      var x = sx + (py - sy) * (tx - sx) / (ty - sy)

      // 点在多边形的边上
      if(x === px) {
        return 'on'
      }

      // 射线穿过多边形的边界
      if(x > px) {
        flag = !flag
      }
    }
  }

  // 射线穿过多边形边界的次数为奇数时点在多边形内
  return flag ? true : false
}
/**
 * @description 回转数法判断点是否在多边形内部
 * @param {Object} p 待判断的点，格式：{ x: X坐标, y: Y坐标 }
 * @param {Array} poly 多边形顶点，数组成员的格式同 p
 * @return {String} 点 p 和多边形 poly 的几何关系
 */
function isInPolygon(p, poly) {
  var px = p.x,
      py = p.y,
      sum = 0

  for(var i = 0, l = poly.length, j = l - 1; i < l; j = i, i++) {
    var sx = poly[i].x,
        sy = poly[i].y,
        tx = poly[j].x,
        ty = poly[j].y

    // 点与多边形顶点重合或在多边形的边上
    if((sx - px) * (px - tx) >= 0 && (sy - py) * (py - ty) >= 0 && (px - sx) * (ty - sy) === (py - sy) * (tx - sx)) {
      return 'on'
    }

    // 点与相邻顶点连线的夹角
    var angle = Math.atan2(sy - py, sx - px) - Math.atan2(ty - py, tx - px)

    // 确保夹角不超出取值范围（-π 到 π）
    if(angle >= Math.PI) {
      angle = angle - Math.PI * 2
    } else if(angle <= -Math.PI) {
      angle = angle + Math.PI * 2
    }

    sum += angle
  }

  // 计算回转数并判断点和多边形的几何关系
  return Math.round(sum / Math.PI) === 0 ? false : true
}
/** 
 *  判断一个点是否在圆的内部 
 *  @param point  测试点坐标 
 *  @param circle 圆心坐标 
 *  @param r 圆半径 
 *  返回true为真，false为假 
 *
 * */
function isInCircle(point, circle, r) {
  if (r===0) return false
  var dx = Math.abs(circle.x - point.x)
  var dy = Math.abs(circle.y - point.y)
  
  return dx * dx + dy * dy <= r * r
}

function getSideLen(xy1, xy2){
  var r = 0, a= 0, b = 0
  a = Math.abs(xy1.x-xy2.x)
  b = Math.abs(xy1.y-xy2.y)
  r = Math.sqrt(Math.pow(a, 2) + Math.pow(b, 2))
  return r
}

function getDeg(xy1, xy2){
  var a= 0, b = 0, r = 0
  a = xy1.x-xy2.x
  b = xy1.y-xy2.y
  r = (Math.atan(b/a) * 180 / Math.PI)+(a > 0 ? 180 : 0)
  return r
}

module.exports = {
  isInPolygon,
  getSideLen,
  getDeg,
  rayCasting,
  isInCircle
}